package vn.cuhanh.utils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import vn.cuhanh.ChooseGameActivity;
import vn.cuhanh.MainActivity;
import vn.cuhanh.R;
import vn.cuhanh.bean.Game;
import vn.cuhanh.bean.Minigame;
import vn.cuhanh.bean.PlayType;
import vn.cuhanh.sys.DBAdapter;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.content.res.Configuration;
import android.content.res.Resources.NotFoundException;
import android.database.Cursor;
import android.database.SQLException;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListAdapter;
import android.widget.ListView;

import com.google.analytics.tracking.android.EasyTracker;
import com.google.analytics.tracking.android.MapBuilder;
import com.google.analytics.tracking.android.Tracker;

public class HelperFunc {
	public static final String log_url = "http://staging.mapi.choapp.vn/api/Services/ProcessData.php?featureName=Cuhanh&dataName=setLog";
	public static final int LOG_TYPE_EXCEPTION = 1;
	public static final int LOG_TYPE_USER_ACTION = 2;
	
	public static void showTextNotification(Activity ctx,
			Intent callBackIntent, String pushStr, String title, int noti_id,
			int gameId) {
		final NotificationManager mNotificationManager = (NotificationManager) ctx
				.getSystemService(Context.NOTIFICATION_SERVICE);

		Notification notification = new Notification(R.drawable.ic_launcher,
				pushStr, System.currentTimeMillis());
		notification.flags = Notification.FLAG_AUTO_CANCEL;

		Context context = ctx.getApplicationContext();
		// Intent notificationIntent = new Intent(this, ZingGameActivity.class);
		if (gameId != -1) {
			// Log.v("........put extra", gameId + "");
			callBackIntent.putExtra("GameId", gameId);
		}
		PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
				callBackIntent, PendingIntent.FLAG_UPDATE_CURRENT);

		notification.setLatestEventInfo(context, title, "", contentIntent);

		mNotificationManager.notify(noti_id, notification);
	}

	// test
	private final static int TIMEOUT = 10000; // 10s

	public static String getDataFromSv(String url) {
		return getDataFromSvNew(url, TIMEOUT, null);
	}

	public static String getDataFromSv(String url, int timeout) {
		return getDataFromSvNew(url, timeout, null);
	}

	public static String getDataFromSv(String url, List<NameValuePair> data) {
		return getDataFromSvNew(url, TIMEOUT, data);
	}

	public static String getDataFromSvNew(String urlTarget, int timeout,
			List<NameValuePair> data) {
		Log.d("getDataFromSv", String.valueOf(urlTarget));
		URL url;
		HttpURLConnection connection = null;
		String urlParameters = "&";
		if (data != null) {
			for (NameValuePair item : data) {
				try {
					if (item != null) {
						urlParameters += item.getName() + "="
								+ URLEncoder.encode(item.getValue(), "UTF-8")
								+ "&";
					}
				} catch (UnsupportedEncodingException e) {
					HelperFunc.readStackTrace(e);
				} catch (java.lang.NullPointerException e) {
					HelperFunc.readStackTrace(e);
				}
			}
			if (urlParameters.startsWith("&")) {
				urlParameters = urlParameters.substring(1);
			}

			if (urlParameters.endsWith("&")) {
				urlParameters.substring(0, urlParameters.length() - 1);
			}
		} else {
			urlParameters = "";
		}

		try {
			// Create connection
			url = new URL(urlTarget);

			connection = (HttpURLConnection) url.openConnection();
			if (urlParameters.length() > 0) {
				connection.setRequestMethod("POST");
			} else {
				connection.setRequestMethod("GET");
			}
			if (urlParameters.length() > 0) {
				connection.setFixedLengthStreamingMode(urlParameters.length());
			} else {
				connection.setChunkedStreamingMode(0);
			}
			connection.setRequestProperty("Content-Type",
					"application/x-www-form-urlencoded");

			connection.setRequestProperty("Content-Length",
					"" + Integer.toString(urlParameters.getBytes().length));
			connection.setRequestProperty("Content-Language", "en-US");
			connection.setReadTimeout(TIMEOUT);
			connection.setConnectTimeout(TIMEOUT);
			connection.setRequestProperty("User-Agent",
					"Mozilla/5.0 ( compatible ) ");
			connection.setRequestProperty("Accept", "*/*");
			connection.setRequestProperty("Accept-Charset", "UTF-8");
			connection.setRequestProperty("Connection", "close");
			System.setProperty("http.keepAlive", "false");
			connection.setUseCaches(false);
			connection.setDoInput(true);
			if (urlParameters.length() > 0) {
				connection.setDoOutput(true);
				// Send request
				DataOutputStream wr = new DataOutputStream(
						connection.getOutputStream());
				wr.writeBytes(urlParameters);
				wr.flush();
				wr.close();
			}
			// Get Response
			InputStream is = connection.getInputStream();
			BufferedReader rd = new BufferedReader(new InputStreamReader(is));
			String line;
			StringBuffer response = new StringBuffer();
			while ((line = rd.readLine()) != null) {
				response.append(line);
				response.append('\r');
			}
			rd.close();
			String result = response.toString();
			Log.d("getDataFromSv", "result: " + String.valueOf(result));
			return result; 

		} catch (SocketTimeoutException e) {
//			Log.w("exception", "Socket timeout exception");
			readStackTrace(e, false, false);
		} catch (java.lang.OutOfMemoryError e) {
//			Log.w("exception", "OutOfMemory exception");
			readStackTrace(e, false, false);
		} catch(java.net.UnknownHostException e) {
			readStackTrace(e, false, false);
		} catch(java.net.SocketException e) {
			readStackTrace(e, false, false);
		}
		catch (Exception e) {
//			Log.w("exception", e.getMessage());
			readStackTrace(e, false, false);
		} finally {
			if (connection != null) {
				connection.disconnect();
			}
		}
		Log.d("getDataFromSv", "result: null");
		return null;
	}

	public static String getDataFromSv(String url, int timeout,
			List<NameValuePair> data) {
		BufferedReader reader = null;
		try {
			// HttpGet httpGet = new HttpGet(url);
			HttpParams httpParameters = new BasicHttpParams();
			httpParameters.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
					HttpVersion.HTTP_1_1);
			// Set the timeout in milliseconds until a connection is
			// established.
			// The default value is zero, that means the timeout is not used.
			HttpConnectionParams.setConnectionTimeout(httpParameters, timeout);
			// Set the default socket timeout (SO_TIMEOUT)
			// in milliseconds which is the timeout for waiting for data.
			// int timeoutSocket = 5000;
			HttpConnectionParams.setSoTimeout(httpParameters, timeout);

			HelperFunc.logDebug("HelperFunc -> post url", url + ";");
			HttpClient client = new DefaultHttpClient(httpParameters);
			// client.getParams().setParameter("http.socket.timeout", timeout);
			HttpPost request = new HttpPost();
			request.setURI(new URI(url));
			// request.setHeader("Content-Type", "text/html");
			// request.setHeader("charset", "UTF-8");
			if (data != null)
				request.setEntity(new UrlEncodedFormEntity(data, "UTF-8"));
			HttpResponse response = client.execute(request);

			reader = new BufferedReader(new InputStreamReader(response
					.getEntity().getContent()));

			StringBuilder builder = new StringBuilder();
			String line;
			while ((line = reader.readLine()) != null) {
				builder.append(line);
			}
			String rs = builder.toString();
			HelperFunc.logDebug("HelperFunc -> post url received data", rs);
			return (rs == null || rs.equals("null")) ? null : rs;
		} catch (SocketTimeoutException e) {
			readStackTrace(e);
		} catch (java.lang.OutOfMemoryError e) {
			readStackTrace(e);
		} catch (Exception e) {
			readStackTrace(e);
		} finally {
			if (reader != null)
				try {
					reader.close();
				} catch (IOException e) {
					readStackTrace(e);
				}
		}
		return null;
	}

	public static String trimLongGameNameTitle(Context ctx, String gameName) {
		int orientation = ctx.getResources().getConfiguration().orientation;
		if (orientation == Configuration.ORIENTATION_LANDSCAPE)
			return gameName;

		int _width = 10;
		// Determine density
		DisplayMetrics metrics = new DisplayMetrics();
		((Activity) ctx).getWindowManager().getDefaultDisplay()
				.getMetrics(metrics);
		int density = metrics.densityDpi;
		switch (density) {
		case DisplayMetrics.DENSITY_HIGH:
			_width = 18;
			break;
		case DisplayMetrics.DENSITY_MEDIUM:
			_width = 17;
			break;
		case DisplayMetrics.DENSITY_LOW:
			_width = 16;
			break;
		default:
			break;
		}

		return gameName.length() >= _width ? gameName.substring(0, _width - 3)
				+ "..." : gameName;
	}

	// public static String readStackTrace(Exception e, boolean isPushSV) {
	// StringWriter sw = new StringWriter();
	// PrintWriter pw = new PrintWriter(sw);
	// e.printStackTrace(pw);
	// if (isPushSV){
	// pushExceptionToSv(sw.toString());
	// }
	// return sw.toString();
	// }
	// public static String readStackTrace(Exception e) {
	// return readStackTrace(e, true);
	// }
	public static String readStackTrace(Throwable e, boolean isPushSV,
			boolean isCrashed) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		e.printStackTrace(pw);
		if (isPushSV) {
			pushExceptionToSv(sw.toString(), isCrashed);
		}
		return sw.toString();
	}

	public static String readStackTrace(Throwable e) {
		e.printStackTrace(); // xxx comment luc release
		return readStackTrace(e, true, false); // xxx change isPushSV to true
	}

	public static String readStackTrace(Throwable e, boolean isCrashed) {
		// e.printStackTrace(); //xxx comment luc release
		return readStackTrace(e, true, isCrashed); // xxx isPushSV change to
													// true
	}

	public static void logDebug(String prefix, String msg) {
		// Log.v(prefix, msg); // xxx comment luc release
	}

	private static void pushExceptionToSv(String e, boolean isCrashed) {
		String appName = "Cuhanh";
		// ZingGameActivity.ctx.getResources().getString(R.string.appName);
		DateFormat fullTime = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
		Date date = new Date();
		if (isCrashed) {
			/*
			 * ChoAppActivity.log(dbName, tbName, "message___" +
			 * e.replaceAll("[^a-zA-Z0-9\\.\\(\\)]+"," ").substring(0,2688) +
			 * "|time___" + fullTime.format(date) +"|app___" + appName
			 * +"|crashed___1");
			 */
		}
		log(LOG_TYPE_EXCEPTION, "message___" + e 
				+ "|time___" + fullTime.format(date)
				+ "|versionCode___" + MainActivity.versionCode
				+ "|versionName___" + MainActivity.versionName
				+ "|app___" + appName);
	}
	
	public static void log(final int type, final String data) {
		Thread thread = new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				List<NameValuePair> arrayData = new ArrayList<NameValuePair>();
				arrayData.add(new BasicNameValuePair("type", String.valueOf(type)));
				arrayData.add(new BasicNameValuePair("data", data));
				getDataFromSv(log_url, arrayData);
			}
		});
		thread.start();
	}
	
//	private static void 

	public static boolean isTablet(Context ctx) {
		Display display = ((Activity) ctx).getWindowManager()
				.getDefaultDisplay();
		DisplayMetrics displayMetrics = new DisplayMetrics();
		display.getMetrics(displayMetrics);

		int width = displayMetrics.widthPixels / displayMetrics.densityDpi;
		int height = displayMetrics.heightPixels / displayMetrics.densityDpi;

		double screenDiagonal = Math.sqrt(width * width + height * height);
		return (screenDiagonal >= 7.0);
	}

	public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
		if (bitmap == null)
			return null;
		Bitmap output = null;
		try {
			output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
					Config.ARGB_8888);
			Canvas canvas = new Canvas(output);

			final int color = 0xff424242;
			final Paint paint = new Paint();
			final Rect rect = new Rect(0, 0, bitmap.getWidth(),
					bitmap.getHeight());
			final RectF rectF = new RectF(rect);
			final float roundPx = pixels;

			paint.setAntiAlias(true);
			canvas.drawARGB(0, 0, 0, 0);
			paint.setColor(color);
			canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

			paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
			canvas.drawBitmap(bitmap, rect, rect, paint);
		} catch (java.lang.OutOfMemoryError e) {
			HelperFunc.readStackTrace(e);
		}
		return output;
	}

	public static void copyStream(InputStream is, OutputStream os) {
		final int buffer_size = 1024;
		try {
			byte[] bytes = new byte[buffer_size];
			for (;;) {
				int count = is.read(bytes, 0, buffer_size);
				if (count == -1)
					break;
				os.write(bytes, 0, count);
			}
		} catch (Exception ex) {
		}
	}

	public static String truncateString(String str, int length) {
		String s = str;
		if (str != null) {
			if (str.length() > length) {
				s = s.substring(0, length) + "...";
			}
		}
		return s;
	}

	public static void setListViewHeightBasedOnChildren(ListView listView) {
		ListAdapter listAdapter = listView.getAdapter();
		if (listAdapter == null) {
			// pre-condition
			return;
		}

		int totalHeight = 0;
		for (int i = 0; i < listAdapter.getCount(); i++) {
			View listItem = listAdapter.getView(i, null, listView);
			listItem.measure(0, 0);
			totalHeight += listItem.getMeasuredHeight();
		}

		ViewGroup.LayoutParams params = listView.getLayoutParams();
		params.height = totalHeight
				+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
		listView.setLayoutParams(params);
	}
	
	public static void setGridViewHeightBasedOnChildren(GridView gridView, int height) {
//		ListAdapter listAdapter = gridView.getAdapter();
//		if (listAdapter == null) {
//			// pre-condition
//			return;
//		}

//		int totalHeight = 0;
//		for (int i = 0; i < listAdapter.getCount(); i+=numCol) {
//			View gridItem = listAdapter.getView(i, null, gridView);
//			gridItem.measure(0, 0);
//			totalHeight += gridItem.getMeasuredHeight();
//			totalHeight += gridView.getVerticalSpacing();
//		}
//		totalHeight -= gridView.getVerticalSpacing();
		ViewGroup.LayoutParams params = gridView.getLayoutParams();
		params.height = height;
		gridView.setLayoutParams(params);
	}

	public static void unbindDrawables(View view) {

		if (view == null) {
			return;
		}
		if (view.getBackground() != null) {
			view.getBackground().setCallback(null);
		}
		if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
			for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
				unbindDrawables(((ViewGroup) view).getChildAt(i));
			}
			((ViewGroup) view).removeAllViews();
		}

	}
	
	public static ArrayList<Game> getGameDataDatabase(Cursor cursor) {
		ArrayList<Game> games = new ArrayList<Game>();
		cursor.moveToFirst();
		while (cursor.isAfterLast() == false) {
			int id = cursor.getInt(cursor.getColumnIndexOrThrow("id"));
			String name = cursor
					.getString(cursor.getColumnIndexOrThrow("name"));
			String image = cursor.getString(cursor
					.getColumnIndexOrThrow("image"));
			String nav_image = cursor.getString(cursor
					.getColumnIndexOrThrow("nav_image"));
			Game obj = new Game(id, name, image, nav_image);
			
			String strFeature = cursor.getString(cursor.getColumnIndexOrThrow("features"));
			String[] strArrayFeatures = strFeature.split(",");
			int[] pages = new int[strArrayFeatures.length];
			for(int i = 0; i < strArrayFeatures.length; i++) {
				pages[i] = Integer.valueOf(strArrayFeatures[i]);
			}
			obj.setPages(pages);
			
			games.add(obj);
			cursor.moveToNext();
		}
		return games;
	}
	
	public static ArrayList<PlayType> getPlayTypesFromDatabase(Cursor cursor) {
		ArrayList<PlayType> playTypes = new ArrayList<PlayType>();
		cursor.moveToFirst();
		while (cursor.isAfterLast() == false) {
			int id = cursor.getInt(cursor.getColumnIndexOrThrow("id"));
			int gameId = cursor.getInt(cursor.getColumnIndexOrThrow("gameId"));
			String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
			String displayName = cursor.getString(cursor.getColumnIndexOrThrow("display_name"));
			String image = cursor.getString(cursor.getColumnIndexOrThrow("image"));
			String descriptionFileName = cursor.getString(cursor.getColumnIndexOrThrow("descript_file_name"));
			PlayType obj = new PlayType(id, gameId, name, displayName, image, descriptionFileName);
			playTypes.add(obj);
			cursor.moveToNext();
		}
		return playTypes;
	}

//	public static void getUserProfile(Context ctx) {
//
//		DBAdapter dbAdapter;
//		Cursor cursor = null;
//		dbAdapter = new DBAdapter(ctx, ctx.getResources().getString(
//				R.string.userTable));
//		try {
//			if (dbAdapter.isClosed())
//				dbAdapter.open();
//			cursor = dbAdapter.fetchAll();
//			cursor.moveToFirst();
//			if (cursor.getCount() > 0) {
//
//				MainActivity.username = cursor.getString(cursor
//						.getColumnIndexOrThrow("username"));
//
//			} else {
//				dbAdapter.delete(null);
//			}
//		} catch (SQLException e) {
//			HelperFunc.readStackTrace(e);
//		} catch (IllegalArgumentException e) {
//			HelperFunc.readStackTrace(e);
//		} finally {
//		}
//		try {
//			if (cursor != null) {
//				cursor.close();
//			}
//			dbAdapter.close();
//		} catch (Exception e) {
//			HelperFunc.readStackTrace(e);
//		}
//
//	}
//
	public static ArrayList<Game> getListGame(Context ctx) {
		DBAdapter dbAdapter;
		Cursor cursor = null;
		dbAdapter = new DBAdapter(ctx, ctx.getResources().getString(
				R.string.gameTable));
		try {
			if (dbAdapter.isClosed()) {
				dbAdapter.open();
			}
			cursor = dbAdapter.fetchAll();

			if (cursor.getCount() > 0) {
				return getGameDataDatabase(cursor);
			} else {
				dbAdapter.delete(null);
				return null;
			}
		} catch (SQLException e) {
			HelperFunc.readStackTrace(e);
		} finally {
			try {
				if (cursor != null) {
					cursor.close();
				}
				dbAdapter.close();
			} catch (Exception e) {
				HelperFunc.readStackTrace(e);
			}
		}
		return null;
	}
	
	public static ArrayList<PlayType> getPlayTypes(Context ctx, int gameId) {
		DBAdapter dbAdapter;
		Cursor cursor = null;
		dbAdapter = new DBAdapter(ctx, ctx.getResources().getString(
				R.string.playTypeTable));
		try {
			if (dbAdapter.isClosed()) {
				dbAdapter.open();
			}
			cursor = dbAdapter.fetch("gameId = " + gameId);

			if (cursor.getCount() > 0) {
				return getPlayTypesFromDatabase(cursor);
			}
		} catch (SQLException e) {
			HelperFunc.readStackTrace(e);
		} finally {
			try {
				if (cursor != null) {
					cursor.close();
				}
				dbAdapter.close();
			} catch (Exception e) {
				HelperFunc.readStackTrace(e);
			}
		}
		return null;
	}

//	public static void getListGameDownloaded(Context ctx) {
//		DBAdapter dbAdapter;
//		Cursor cursor = null;
//		MainActivity.setGameDownloaded = new HashSet<String>();
//		dbAdapter = new DBAdapter(ctx, ctx.getResources().getString(
//				R.string.table));
//		try {
//			if (dbAdapter.isClosed()) {
//				dbAdapter.open();
//			}
//		} catch (SQLException e) {
//
//			HelperFunc.readStackTrace(e);
//		}
//		try {
//			MainActivity.setGameDownloaded.clear();
//
//			cursor = dbAdapter.fetchAll();
//			cursor.moveToFirst();
//			while (cursor.isAfterLast() == false) {
//				String id = cursor.getString(cursor
//						.getColumnIndexOrThrow("_id"));
//
//				MainActivity.setGameDownloaded.add(id);
//				cursor.moveToNext();
//			}
//
//		} catch (Exception e) {
//			HelperFunc.readStackTrace(e);
//		} finally {
//			try {
//				if (cursor != null) {
//					cursor.close();
//				}
//				dbAdapter.close();
//			} catch (Exception e) {
//				HelperFunc.readStackTrace(e);
//			}
//		}
//
//	}
//
	public static void logUserAction(Minigame g, Context ctx) {
		try {
			DateFormat dateFormatTB = new SimpleDateFormat("yyyyMM");
			Date date = new Date();
			int curVersion = ctx.getPackageManager().getPackageInfo(
					ctx.getResources().getString(R.string.app_package), 0).versionCode;
			String str = "dbname___"
					+ ctx.getResources().getString(R.string.databaseLog)
					+ "|"
					+ // dbname
					"dbtable___"
					+ ctx.getResources().getString(R.string.tbActivitiesLog)
					+ "_" + dateFormatTB.format(date) + "|" + // dbtable
					"username___" + MainActivity.username + "|" + // username
					"actionId___" + g.getId() + "|" + 
					"apiVersion___" + Build.VERSION.SDK_INT + "|" + // version
					"model___" + android.os.Build.MANUFACTURER + "|" + // model
					"os___" + "Android" + "|" + // os
					"imei___" + MainActivity.deviceImei + "|" + // imei
					"app_version___" + String.valueOf(curVersion) + "|" + // app
					// version
					"source___" + "source" + "|" + // source
																		// install
																		// from
					"context___" + ctx.getClass().getName() + "|" + // context
					"productId" + ChooseGameActivity.current.getId(); // game id

			List<NameValuePair> logData = new ArrayList<NameValuePair>(1);
			logData.add(new BasicNameValuePair(0 + "", str));
			final String svResponse = HelperFunc.getDataFromSv(ctx
					.getResources().getString(R.string.postLogUrl), logData);

			boolean pushLogSuccess = true;
			if (svResponse != null && svResponse != "") {

				if ("1".equals(svResponse)) {
					HelperFunc.logDebug("..onDownload", "Push log successful");
				} else {
					pushLogSuccess = false;
				}
			} else {
				pushLogSuccess = false;
			}

			if (!pushLogSuccess) {
				ContentValues data = new ContentValues();
				data.put("log", str);
				SystemLog systemLog = new SystemLog(ctx);
				systemLog.log(data);
				HelperFunc
						.logDebug("..onDownload", "Push log fail write to db");
			}
		} catch (NumberFormatException e) {
			HelperFunc.readStackTrace(e);
		} catch (NotFoundException e) {
			HelperFunc.readStackTrace(e);
		} catch (NameNotFoundException e) {
			HelperFunc.readStackTrace(e);
		} catch (NullPointerException e) {
			HelperFunc.readStackTrace(e);
		}
	}

//	public static void logStart(Context ctx) {
//		try {
//			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//			DateFormat dateFormatTB = new SimpleDateFormat("yyyyMMdd");
//			Date date = new Date();
//			int curVersion = ctx.getPackageManager().getPackageInfo(
//					ctx.getResources().getString(R.string.app_package), 0).versionCode;
//			String str = "dbname___"
//					+ ctx.getResources().getString(R.string.databaseLog)
//					+ "|"
//					+ // dbname
//					"dbtable___"
//					+ ctx.getResources().getString(R.string.tbActivitiesLog)
//					+ "_" + dateFormatTB.format(date) + "|"
//
//					+ "type___" + "onStart" + "|" + // username
//					"api_version___" + Build.VERSION.SDK_INT + "|" + // version
//					"model___" + android.os.Build.MANUFACTURER + "|" + // model
//					"time___" + dateFormat.format(date) + "|" + // event fired
//																// time
//					"component___" + "onStart" + "|" + // view
//					"os___" + "Android" + "|" + // os
//					"imei___" + Splash.deviceImei + "|" + // imei
//					"source___" + Splash.sourceInstall + "|" + // source
//																		// install
//																		// from
//					"context___" + ctx.getClass().getName() + "|" + // context
//					"app_version___" + String.valueOf(curVersion);
//
//			List<NameValuePair> logData = new ArrayList<NameValuePair>(1);
//			logData.add(new BasicNameValuePair(0 + "", str));
//			final String svResponse = HelperFunc.getDataFromSv(ctx
//					.getResources().getString(R.string.postLogUrl), logData);
//
//			boolean pushLogSuccess = true;
//			if (svResponse != null && svResponse != "") {
//				int status = Integer.parseInt(svResponse);
//				if (status == 1) {
//					HelperFunc.logDebug("..onDownload", "Push log successful");
//				} else {
//					pushLogSuccess = false;
//				}
//			} else {
//				pushLogSuccess = false;
//			}
//
//		} catch (NumberFormatException e) {
//			HelperFunc.readStackTrace(e);
//		} catch (NotFoundException e) {
//			HelperFunc.readStackTrace(e);
//		} catch (NameNotFoundException e) {
//			HelperFunc.readStackTrace(e);
//		} catch (NullPointerException e) {
//			HelperFunc.readStackTrace(e);
//		} catch (Exception e) {
//			HelperFunc.readStackTrace(e);
//		}
//	}
//
//	public static void logOut(Context ctx) {
//		try {
//			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//			DateFormat dateFormatTB = new SimpleDateFormat("yyyyMMdd");
//			Date date = new Date();
//			int curVersion = ctx.getPackageManager().getPackageInfo(
//					ctx.getResources().getString(R.string.app_package), 0).versionCode;
//			String str = "dbname___"
//					+ ctx.getResources().getString(R.string.databaseLog)
//					+ "|"
//					+ // dbname
//					"dbtable___"
//					+ ctx.getResources().getString(R.string.tbActivitiesLog)
//					+ "_" + dateFormatTB.format(date) + "|"
//					+ // dbtable
//					"transaction_id___" + MainActivity.transactionId + "|"
//					+ // transaction_id
//					"type___" + "onClose" + "|" + "username___"
//					+ MainActivity.username + "|" + // username
//					"api_version___" + Build.VERSION.SDK_INT + "|" + // version
//					"model___" + android.os.Build.MANUFACTURER + "|" + // model
//					"time___" + dateFormat.format(date) + "|" + // event fired
//																// time
//					"component___" + "onClose" + "|" + // view
//					"os___" + "Android" + "|" + // os
//					"imei___" + HomeActivity.deviceImei + "|" + // imei
//					"source___" + HomeActivity.sourceInstall + "|" + // source
//																		// install
//																		// from
//					"context___" + ctx.getClass().getName() + "|" + // context
//					"app_version___" + String.valueOf(curVersion);
//
//			List<NameValuePair> logData = new ArrayList<NameValuePair>(1);
//			logData.add(new BasicNameValuePair(0 + "", str));
//			final String svResponse = HelperFunc.getDataFromSv(ctx
//					.getResources().getString(R.string.postLogUrl), logData);
//
//			boolean pushLogSuccess = true;
//			if (svResponse != null && svResponse != "") {
//				int status = Integer.parseInt(svResponse);
//				if (status == 1) {
//					HelperFunc.logDebug("..onDownload", "Push log successful");
//				} else {
//					pushLogSuccess = false;
//				}
//			} else {
//				pushLogSuccess = false;
//			}
//
//		} catch (NumberFormatException e) {
//			HelperFunc.readStackTrace(e);
//		} catch (NotFoundException e) {
//			HelperFunc.readStackTrace(e);
//		} catch (NameNotFoundException e) {
//			HelperFunc.readStackTrace(e);
//		} catch (NullPointerException e) {
//			HelperFunc.readStackTrace(e);
//		} catch (Exception e) {
//			HelperFunc.readStackTrace(e);
//		}
//	}
	public static void  showSimpleAlertDialog(Context ctx, String title, String message, 
			String positiveBtnTitle, DialogInterface.OnClickListener positiveListener, 
			String negativeBtnTitle, DialogInterface.OnClickListener negativeListener,
			boolean cancelable) {
		showSimpleAlertDialog(ctx, title, message, 
				positiveBtnTitle, positiveListener, 
				null, null,
				negativeBtnTitle, negativeListener,
				cancelable);
	}

	public static void  showSimpleAlertDialog(Context ctx, String title, String message, 
			String positiveBtnTitle, DialogInterface.OnClickListener positiveListener, 
			String neutralBtnTitle, DialogInterface.OnClickListener neutralBtnListener,
			String negativeBtnTitle, DialogInterface.OnClickListener negativeListener,
			boolean cancelable) {
		AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
				ctx);
			alertDialogBuilder.setInverseBackgroundForced(true);
			// set title
			alertDialogBuilder.setTitle(title);
//			LayoutInflater inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//			View view = inflater.inflate(R.layout.alert_dialog_body, null);
//			TextView textView = (TextView)view.findViewById(R.id.alert_dialog_message);
//			textView.setText(message);
//			alertDialogBuilder.setView(view);
			// set dialog message
			alertDialogBuilder
			.setMessage(message)
			.setCancelable(cancelable);
			if(positiveBtnTitle == null && negativeBtnTitle == null && neutralBtnTitle == null) {
				alertDialogBuilder.setNegativeButton(ctx.getResources().getString(R.string.close), null);
			} else {
				if(positiveBtnTitle != null) {
					alertDialogBuilder.setPositiveButton(positiveBtnTitle, positiveListener);
				} 
				if(neutralBtnTitle != null) {
					alertDialogBuilder.setNeutralButton(neutralBtnTitle, neutralBtnListener);
				}
				if(negativeBtnTitle != null) {
					alertDialogBuilder.setNegativeButton(negativeBtnTitle, negativeListener);
				}
			}
			// create alert dialog
			AlertDialog alertDialog = alertDialogBuilder.create();

			// show it
			try {
				alertDialog.show();
			} catch (Exception e) {
				// TODO: handle exception
				HelperFunc.readStackTrace(e);
			}
	}
	
	public static void showAlertDialogOnUiThread(final Context ctx, final String title, final String message) {
		((Activity)ctx).runOnUiThread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				HelperFunc.showSimpleAlertDialog(ctx, 
						title, 
						message, 
						ctx.getResources().getString(R.string.bt_ok_title), 
						null, null, null, true);
			}
		});
	}
	
	public static String slugify(String input) {
        String ret = input.trim();
        ret = ret.replace('đ', 'd').replace('Đ', 'D');
        if (ret == null || ret.isEmpty()) {
               return "";
        }

        ret = normalize(ret);
        ret = removeDuplicateWhiteSpaces(ret);
        return ret.replace(" ", "-").toLowerCase();
	 }
	
	 private static String normalize(String input) {
	        String result = Normalizer.normalize(input, Form.NFD).replaceAll("[^\\p{ASCII}]", ""); // 1
	        result = result.replaceAll("[^a-zA-Z0-9\\s]", " "); // 2
	        return result;
	 }
	
	 private static String removeDuplicateWhiteSpaces(String input) {
	        return input.replaceAll("\\s+", " ");
	 }

	 /** Read the object from Base64 string. */
    public static Object Deserialize( String s ) throws IOException ,
                                                        ClassNotFoundException {
        byte [] data = Base64.decode(s, Base64.DEFAULT);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data) );
        Object o  = ois.readObject();
        ois.close();
        return o;
    }

    /** Write the object to a Base64 string. */
    public static String Serialize( Serializable o ) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream( baos );
        oos.writeObject( o );
        oos.close();
        return new String( Base64.encode( baos.toByteArray(), Base64.DEFAULT ) );
    }
    
    public static void expand(final View v, final int minHeight) {
        v.measure(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
        final int targtetHeight = v.getMeasuredHeight();
        Log.d("expand", "targetHeight: " + String.valueOf(targtetHeight));
        v.setVisibility(View.VISIBLE);
        Animation a = new Animation()
        {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                v.getLayoutParams().height = interpolatedTime == 1
                        ? LayoutParams.WRAP_CONTENT
                        : (int)(minHeight + (targtetHeight - minHeight) * interpolatedTime);
                Log.d("expand", String.valueOf((int)(minHeight + (targtetHeight - minHeight) * interpolatedTime)));
                v.requestLayout();
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        // 1dp/ms
        a.setDuration((int)(targtetHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }

    public static void collapse(final View v, final int minHeight) {
        final int initialHeight = v.getMeasuredHeight();

        Animation a = new Animation()
        {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                v.getLayoutParams().height = initialHeight - (int)((initialHeight - minHeight)  * interpolatedTime);
                v.requestLayout();
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        // 1dp/ms
        a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }
    
    public static String getAssetFileContent(Context ctx, String fileName) throws IOException {
    	StringBuffer fileData = new StringBuffer(1000);
    	InputStream input = ctx.getAssets().open(fileName);
    	Reader reader = new InputStreamReader(input, "UTF-8");
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            String readData = String.valueOf(buf, 0, numRead);
            fileData.append(readData);
        }
        reader.close();
        return fileData.toString();
    }
    
    public static int indexOfIntArray(int[] array, int value){
		for(int i = 0; i < array.length; i++){
			if(array[i] == value){
				return i;
			}
		}
		return -1;
	}
    
	public static Bitmap getBitmapFromAsset(Context ctx, String strName) throws IOException
	{
		Bitmap bitmap = null;
		try {
		    InputStream istr = ctx.getAssets().open(strName);
		    bitmap = BitmapFactory.decodeStream(istr);
		} catch (OutOfMemoryError e) {
			// TODO: handle exception
			HelperFunc.readStackTrace(e);
		}
	    return bitmap;
	}
	
	public static String secondToTime(Context ctx, int second) {
		int hour = (int) (second / 3600);
		int minute = (int) ((second % 3600) / 60);
		int sec = (int) (second % 60);
		return (hour > 0 ? (String.valueOf(hour) + " " + ctx.getResources().getString(R.string.hour) + " ") : "")
		+ (minute > 0 || hour > 0 ? (String.valueOf(minute) + " " + ctx.getResources().getString(R.string.minute) + " ") : "")
		+ String.valueOf(sec) + " " + ctx.getResources().getString(R.string.second);
	}

	public static String secondToTime(Context ctx, Long second) {
		// TODO Auto-generated method stub
		return HelperFunc.secondToTime(ctx, Integer.valueOf(second.toString()));
	}
	
	public static void showHashKey(Context ctx) {
		 try {
		        PackageInfo info = ctx.getPackageManager().getPackageInfo(
		                "vn.cuhanh", 
		                PackageManager.GET_SIGNATURES);
		        for (Signature signature : info.signatures) {
		            MessageDigest md = MessageDigest.getInstance("SHA");
		            md.update(signature.toByteArray());
		            Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
		            }
		    } catch (NameNotFoundException e) {

		    } catch (NoSuchAlgorithmException e) {

		    }
	}
	
	public static void trackEvent(Context ctx, String category, String action, String label, Long value) {
		if(ctx == null || category == null || action == null) {
			return;
		}
		
		EasyTracker at = EasyTracker.getInstance(ctx);
		if(at == null) {
			return;
		}
		at.send(MapBuilder.createEvent(category,     // Event category (required)
		                   action,  // Event action (required)
		                   label,   // Event label
		                   value)            // Event value
		      .build()
		  );
	}
	
	public static void trackEvent(Context ctx, String category, String action, String label) {
		trackEvent(ctx, category, action, label, null);
	}
}
